package com.ytclub.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.gson.Gson;
import com.ytclub.auth.common.enums.AuthUserStatusEnum;
import com.ytclub.auth.common.enums.IsDeletedFlagEnum;
import com.ytclub.auth.domain.constants.AuthConstant;
import com.ytclub.auth.domain.convent.AuthUserBOConverter;
import com.ytclub.auth.domain.entity.AuthUserBO;
import com.ytclub.auth.domain.redis.RedisUtil;
import com.ytclub.auth.domain.service.AuthUserDoaminService;
import com.ytclub.auth.infra.basic.entity.*;
import com.ytclub.auth.infra.basic.service.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户领域层接口实现类
 *
 * @author: HuangQi
 * @date: Created in 21:14 2023/12/19
 * @description: 用户领域层接口实现类
 */
@Service
@Slf4j
public class AuthUserDoaminServiceImpl implements AuthUserDoaminService {

    private String salt = "ytclub";

    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;

    @Resource
    private AuthPermissionService authPermissionService;

    @Resource
    private RedisUtil redisUtil;


    /**
     * 注册用户
     *
     * @param authUserBO 新增用户的信息
     * @return 注册结果
     */
    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDoaminServiceImpl.register.bo:{}", JSON.toJSONString(authUserBO));
        }


        // 参数转换
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        // 校验用户是否存在
        if (this.isExistUser(authUser.getUserName())) {
            return false;
        }
        // 密码加密
        if (StringUtils.isNotBlank(authUser.getPassword())) {
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), salt));
        }

        if (org.apache.commons.lang3.StringUtils.isBlank(authUser.getAvatar())) {
            authUser.setAvatar("http://117.72.10.84:9000/user/icon/微信图片_20231203153718(1).png");
        }

        if (org.apache.commons.lang3.StringUtils.isBlank(authUser.getNickName())) {
            authUser.setNickName("猿粉丝");
        }

        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());

        // 调用service
        Integer count = authUserService.insert(authUser);

        // 建立一个初步的角色关联
        // 用户-角色关联(普通用户)
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole roleResult = authRoleService.queryByCondition(authRole);
        Long roleId = roleResult.getId();
        Long userId = authUser.getId();

        // 建立用户和角色的关联(插入一条数据到用户角色关联表)
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setRoleId(roleId);
        authUserRole.setUserId(userId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);

        // 要把当前用户的角色和权限都刷到我们的redis里面
        String roleKey = redisUtil.buildKey(AuthConstant.AUTH_ROLE_PREFIX, authUser.getUserName());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        redisUtil.set(roleKey, new Gson().toJson(roleList));

        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);

        // 在角色权限表中查询permissionId集合
        List<AuthRolePermission> rolePermissionList = authRolePermissionService.queryByCondition(authRolePermission);
        List<Long> permissionIdList = rolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId).collect(Collectors.toList());

        // 根据permissionId去权限表中查权限
        List<AuthPermission> permissionList = authPermissionService.queryByPermisionIdList(permissionIdList);
        String permissionKey = redisUtil.buildKey(AuthConstant.AUTH_PERMISSION_PREFIX, authUser.getUserName());
        redisUtil.set(permissionKey, new Gson().toJson(permissionList));

        // 返回结果
        return count > 0;
    }

    /**
     * 更新用户信息
     *
     * @param authUserBO 更新用户的信息
     * @return 更新结果
     */
    @Override
    public Boolean update(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDoaminServiceImpl.update.bo:{}", JSON.toJSONString(authUserBO));
        }

        // 参数转换
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);

        // 调用service
        Integer count = authUserService.updateByUserName(authUser);

        // 有任何更新,都要与缓存进行同步的修改

        // 返回结果
        return count > 0;
    }


    /**
     * 删除用户
     *
     * @param authUserBO 删除用户的信息
     * @return 删除结果
     */
    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDoaminServiceImpl.delete.bo:{}", JSON.toJSONString(authUserBO));
        }

        // 参数转换
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());

        // 调用service
        Integer count = authUserService.update(authUser);

        // 有任何更新,都要与缓存进行同步的修改

        // 返回结果
        return count > 0;
    }

    /**
     * 用户登录
     *
     * @param validCode 验证码
     * @return 登录结果
     */
    @Override
    public SaTokenInfo doLogin(String validCode) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDoaminServiceImpl.doLogin.validCode:{}", JSON.toJSONString(validCode));
        }
        // 从redis中获取openId
        String loginKey = redisUtil.buildKey(AuthConstant.LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(loginKey);
        if (StringUtils.isBlank(openId)) {
            return null;
        }

        // 判断用户是否存在
        if (!this.isExistUser(openId)) {
            AuthUserBO authUserBO = new AuthUserBO();
            authUserBO.setUserName(openId);
            this.register(authUserBO);
        }

        // 登录
        StpUtil.login(openId);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        log.info("登录成功,tokenInfo:{}", JSON.toJSONString(tokenInfo));
        return tokenInfo;
    }

    /**
     * 获取用户信息
     *
     * @param authUserBO 需要获取的用户
     * @return 用户信息
     */
    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthUserDoaminServiceImpl.getUserInfo.bo:{}", JSON.toJSONString(authUserBO));
        }

        // 参数转换
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> userList = authUserService.queryByCondition(authUser);

        // 返回结果
        if (CollectionUtils.isEmpty(userList)) {
            return new AuthUserBO();
        }
        AuthUser userInfo = userList.get(0);
        return AuthUserBOConverter.INSTANCE.convertEntityToBO(userInfo);
    }

    /**
     * 判断用户是否存在
     */
    public Boolean isExistUser(String userName) {
        AuthUser authUser = authUserService.queryByUserName(userName);
        return !Objects.isNull(authUser);

    }


}
